home *** CD-ROM | disk | FTP | other *** search
/ La Traviata / La Traviata.iso / viewer / gif.arc / NLZW.ASM < prev    next >
Assembly Source File  |  1988-02-09  |  13KB  |  342 lines

  1. ;**************************************************************************
  2. ;Written 1/27/88-2/6/88 by Jim Griebel
  3. ;Built as a Turbo external OBJ file, this routine replaces READCODE,
  4. ;ADDTOPIXEL and all the high-level LZW decoding done by GIFSLOW.
  5. ;**************************************************************************
  6.  
  7. data        segment word public
  8.             assume ds:data
  9.  
  10. ;definitions for Turbo variables used in this module
  11.  
  12.             extrn clear:byte,interlace:byte,pass:byte
  13.             extrn freecode:word,clearcode:word,bitmask:word
  14.             extrn width:word,maxcode:word,codesize:word
  15.             extrn readmask:word,eofcode:word,height:word
  16.             extrn bitsperpixel:byte
  17.             extrn linestart:word
  18.             extrn nextraster:byte
  19.             extrn raster:dword
  20.             extrn palette:byte
  21.  
  22. ;And for variables declared locally
  23.  
  24.             bitoffset  dw 0
  25.             bitoffset2 dw 0
  26.             yc      dw ?
  27.             oldcolor db ?
  28.             yoffset dw ?
  29.             xoffset dw ?
  30.             curcode dw ?
  31.             incode  dw ?
  32.             oldcode dw ?
  33.             finchar db ?
  34.             rasterseg dw ?
  35.             rasterofs dw ?
  36.             prefix  dw 4096 dup (?)
  37.             suffix  db 4096 dup (?)
  38.             outcode db 1024 dup (?)
  39.             scanline db 640 dup (?)
  40.  
  41. data        ends
  42.  
  43. cseg        segment byte public
  44.  
  45.             assume cs:cseg
  46.  
  47. ;We retain some Turbo calls just to keep things simple
  48.  
  49.             extrn doclear:near
  50.             extrn moveup:near
  51.  
  52.             public nlzw
  53.  
  54. nlzw        proc   near
  55.  
  56. ;Here's where the fun starts. Do the necessary preliminaries, including
  57. ;setting constants and variable starting points since Turbo won't let
  58. ;us declare them
  59.  
  60.             mov    byte ptr oldcolor,255 ;Set oldcolor to a null value
  61.             xor    ax,ax            ;Set bitoffset to start of file
  62.             mov    bitoffset,ax
  63.             mov    bitoffset2,ax
  64.             mov    yoffset,ax       ;YOFFSET to origin of screen RAM
  65.             mov    xoffset,ax       ;Ditto for XOFFSET
  66.             mov    yc,ax            ;Zero out Y-coord
  67.  
  68. ;Here's the main loop where the file is decompressed and displayed
  69.  
  70. top:        call   readcode         ;Extract GIF compression code
  71.             push   ds
  72.             pop    es
  73.             lea    di,outcode       ;Aim DI at the output queue
  74.             mov    bx,bitmask       ;Get the bitmask in BX
  75.             xor    dx,dx            ;Zero out DX, used as output counter
  76.             cmp    ax,eofcode       ;Are we at the end of image?
  77.             jnz    ckclear          ;Nope, press on
  78.             jmp    finis            ;Yes, done, exit
  79. ckclear:    cmp    ax,clearcode     ;Did we read a CLEAR code?
  80.             jnz    noclear          ;Nope
  81.             inc    byte ptr clear   ;Yes, turn on the CLEAR flag
  82.             push   es
  83.             push   di
  84.             push   dx
  85.             push   bx
  86.             call   doclear          ;Reset values to initial
  87.             call   readcode         ;Read raw data
  88.             pop    bx
  89.             pop    dx
  90.             pop    di
  91.             pop    es
  92.             mov    oldcode,ax       ;Set OLDCODE to value just read
  93.             jmp    done             ;and go put that out
  94. noclear:    mov    curcode,ax       ;Otherwise, check for new data
  95.             mov    incode,ax
  96.             cmp    ax,freecode      ;See if >= freecode, if so
  97.             jl     notnew           ;Not new, already in table
  98.             mov    ax,oldcode       ;Otherwise curcode=oldcode
  99.             mov    curcode,ax
  100.             mov    al,finchar       ;stack last char decoded for output
  101.             stosb
  102.             inc    dx               ;increment the count
  103. notnew:     mov    ax,curcode       ;Run the hash table for this value
  104.             cmp    ax,bx            ;Current code less than BITMASK?
  105.             jle    done             ;Yes, bail out
  106. loop:       mov    si,ax
  107.             mov    al,[si+suffix]   ;otherwise stack suffix [curcode]
  108.             stosb                   ;for output
  109.             inc    dx
  110.             shl    si,1
  111.             mov    ax,[si+prefix]   ;and set curcode=prefix [curcode]
  112.             mov    curcode,ax
  113.             cmp    ax,bx            ;If not done, continue
  114.             jg     loop
  115. done:       and    ax,bx            ;Mask off actual data
  116.             mov    finchar,al       ;Save as FINCHAR
  117.             stosb                   ;And put it on output queue
  118.             mov    si,di            ;Outqueue pointer to SI
  119.             dec    si               ;Back up to valid data
  120.             mov    cx,dx            ;Output count to CX
  121.             inc    cx               ;Make good count for LOOP
  122.             push   es
  123.             std
  124.             push   ds               ;Point ES:DI to SCANLINE
  125.             pop    es
  126.             lea    di,scanline
  127.             add    di,xoffset       ;Point into current pos in SCANLINE
  128.             mov    dx,xoffset       ;DX now serves as pos counter
  129. scanloop:   lodsb                   ;get byte from output queue. Stacked
  130.             stosb                   ;LIFO, so deal with it that way
  131.             inc    di               ;overcome auto-decrement
  132.             inc    di
  133.             inc    dx               ;At end of current scan line?
  134.             cmp    dx,width
  135.             jnz    scanloop1        ;Nope, press on
  136.             call   putout           ;Yup, put out the scan line
  137. scanloop1:  loop   scanloop         ;Continue for length of outqueue
  138.             mov    xoffset,dx       ;Save new pos
  139.             cld                     ;Dir flag back to normal
  140.             pop    es               ;ES back to DS
  141. noout:      cmp    byte ptr clear,0 ;Are we doing a CLEAR?
  142.             jz     goon             ;No, proceed
  143.             dec    byte ptr clear   ;Yes, turn off CLEAR flag
  144.             jmp    top              ;and take the short way out
  145. goon:       mov    di,freecode      ;suffix[freecode]=finchar
  146.             mov    al,finchar
  147.             mov    [di+suffix],al
  148.             shl    di,1             ;Adjust for word-sized array
  149.             mov    ax,oldcode       ;Prefix [freecode]=oldcode
  150.             mov    [di+prefix],ax
  151.             mov    ax,incode        ;Set Oldcode=Incode
  152.             mov    oldcode,ax
  153.             mov    ax,freecode      ;Kick to next free code
  154.             inc    ax
  155.             mov    freecode,ax
  156.             cmp    ax,maxcode       ;Increase code size if necessary
  157.             jge    incmax           ;(and possible, 12 is limit)
  158.             jmp    top
  159. incmax:     mov    ax,maxcode       ;maxcode = maxcode * 2
  160.             shl    ax,1
  161.             mov    maxcode,ax
  162.             mov    ax,codesize      ;If codesize < 12, increment it
  163.             cmp    ax,12
  164.             jnz    inccode
  165.             jmp    top
  166. inccode:    inc    ax
  167.             mov    codesize,ax
  168.             mov    cl,al            ;Compute new READMASK value
  169.             xor    ch,ch
  170.             mov    ax,1
  171.             shl    ax,cl
  172.             dec    ax
  173.             mov    readmask,ax
  174.             jmp    top
  175. finis:      ret                      ;Whole image done, exit
  176.  
  177. nlzw        ENDP
  178.  
  179. ;Put out the array of pixels stored in SCANLINE
  180.  
  181. putout      proc   near
  182.             push   es                ;Push sensitive regs
  183.             push   cx
  184.             push   ds
  185.             push   si
  186.             cld                      ;Because caller does STD
  187.             mov    ax,0a000h         ;EGA video segment address
  188.             mov    es,ax
  189.             mov    bl,80h            ;Current pos in byte
  190.             mov    bh,oldcolor
  191.             mov    di,yoffset        ;Current Y pos in screen RAM
  192.             lea    si,scanline
  193.             mov    dx,3CEH           ;DX gets EGA register address
  194.             mov    cx,width
  195. outloop:    lodsb                    ;Get byte from output queue
  196.             cmp    al,15
  197.             jle    outgo
  198.             push   si
  199.             xor    ah,ah
  200.             mov    si,ax
  201.             mov    al,[si+palette]
  202.             pop    si
  203. outgo:      cmp    al,bh             ;Same as old color?
  204.             jz     skipit            ;Yes, no need to tell EGA new one
  205.             mov    bh,al             ;Set new color as old color
  206.             xchg   ah,al
  207.             xor    al,al             ;Index 0
  208.             out    dx,ax             ;Put out both values at once
  209. skipit:     mov    al,8              ;Now point to mask reg
  210.             mov    ah,bl
  211.             out    dx,ax
  212.             mov    al,es:[di]        ;Latch data by read/write memory
  213.             stosb
  214.             dec    di                ;compensate for auto-increment
  215.             shr    bl,1              ;Shift mask to next bit pos
  216.             or     bl,bl             ;Out of mask?
  217.             jnz    loop1             ;No, skip
  218.             mov    bl,80H            ;Yes, reset mask to top bit
  219.             inc    di                ;DI to next screen byte
  220. loop1:      loop   outloop           ;And keep on
  221.             call   incyc             ;Kick YC and Yoffset to next line
  222.             call   computey
  223.             lea    di,scanline       ;Point DI back to start of scanline
  224.             xor    dx,dx             ;Pos pointer back to 0
  225.             std                      ;set this back the right (wrong) way
  226.             mov    oldcolor,bh       ;save oldcolor for next time
  227.             pop    si
  228.             pop    ds
  229.             pop    cx
  230.             pop    es
  231.             ret
  232.  
  233. putout      endp
  234.  
  235. ;Compute starting position of this screen line in EGA memory. Just gets
  236. ;appropriate value from LINESTART
  237.  
  238. computey    proc   near
  239.             push   ax
  240.             push   si
  241.             mov    ax,yc
  242.             shl    ax,1
  243.             lea    si,linestart
  244.             add    si,ax
  245.             lodsw
  246.             mov    yoffset,ax
  247.             pop    si
  248.             pop    ax
  249.             ret
  250. computey    endp
  251.  
  252. ;Increment YC if the picture is non-interlaced, otherwise cope with
  253. ;interlace
  254.  
  255. incyc       proc   near
  256.             mov    ax,yc
  257.             cmp    ax,479     ;Quit if we'll overflow EGA bounds
  258.             jnz    incit      ;otherwise increment
  259.             ret
  260. incit:      cmp    byte ptr interlace,0
  261.             jz     simple
  262.             cmp    byte ptr pass,0
  263.             jnz    in2
  264.             add    ax,8
  265.             mov    yc,ax
  266.             cmp    ax,word ptr height
  267.             jl     fin
  268.             inc    byte ptr pass
  269.             mov    word ptr yc,4
  270.             ret
  271. in2:        cmp    byte ptr pass,1
  272.             jnz    in3
  273.             add    ax,8
  274.             mov    yc,ax
  275.             cmp    ax,word ptr height
  276.             jl     fin
  277.             inc    byte ptr pass
  278.             mov    word ptr yc,2
  279.             ret
  280. in3:        cmp    byte ptr pass,2
  281.             jnz    in4
  282.             add    ax,4
  283.             mov    yc,ax
  284.             cmp    ax,word ptr height
  285.             jl     fin
  286.             inc    byte ptr pass
  287.             mov    word ptr yc,1
  288.             ret
  289. in4:        add    ax,2
  290.             mov    yc,ax
  291.             ret
  292. simple:     inc    ax
  293.             mov    yc,ax
  294. fin:        ret
  295. incyc       endp
  296.  
  297. ;This code replaces READCODE. Pick up a 24-bit chunk from the RASTER
  298. ;array and make a code of the necessary size out of it. Cope with files
  299. ;larger than 64000 bytes here also
  300.  
  301. readcode    proc   near
  302.             mov    ax,bitoffset
  303.             mov    dx,bitoffset2
  304.             add    ax,codesize
  305.             adc    dx,0
  306.             xchg   ax,bitoffset
  307.             xchg   dx,bitoffset2
  308.             mov    cx,8
  309.             div    cx
  310.             push   ax
  311.             push   ds
  312.             lds    si,raster
  313.             add    si,ax
  314.             les    bx,[si]
  315.             mov    ax,es
  316.             pop    ds
  317.             mov    cx,dx
  318.             jcxz   noshift
  319. shift:      shr    al,1
  320.             rcr    bx,1
  321.             loop   shift
  322. noshift:    and    bx,readmask
  323.             pop    ax
  324.             cmp    byte ptr nextraster,1
  325.             jnz    rdone
  326.             cmp    ah,0f6h
  327.             jnz    rdone
  328.             push   bx
  329.             mov    ax,ds
  330.             push   ax
  331.             lea    ax,bitoffset
  332.             push   ax
  333.             call   moveup
  334.             pop    bx
  335. rdone:      mov    ax,bx
  336.             ret
  337. readcode    endp
  338.  
  339. nlzw        endp
  340.             cseg   ends
  341.             end    nlzw
  342.             end